from . import _have_config, _set_config, _get_config
from . import log
from .errors import CheckError
import os
from ruamel import yaml


class _MugenConfig:
    def __init__(self, yaml_file: str, set_default=False):
        assert yaml_file is not None, 'yaml_file should not be None'
        if yaml_file.strip() == '':
            raise CheckError('yaml_file should not be empty')
        if not set_default and not os.path.exists(yaml_file):
            raise CheckError('yaml_file should be exists')
        if not set_default and not os.path.isfile(yaml_file):
            raise CheckError('yaml_file should be a regular file')
        if set_default and os.path.exists(yaml_file) and not os.path.isfile(yaml_file):
            raise CheckError('yaml_file exists and not a regular file')

        if yaml_file[0] not in ['.', '/']:
            yaml_file = f'./{yaml_file}'
        self._yaml_file = yaml_file
        self._set_default = set_default
        self._config_dict = {'suite_list': '',
                             'workspace': '',

                             'qcow2_image': 'mugen-ready.qcow2',
                             'virt_cpu': '',
                             'virt_vcpus': '4',
                             'virt_mem': '4096',
                             'virt_arch': 'x86_64',
                             'virt_boot': 'uefi',
                             'virt_install': '',
                             'virt_network': 'default',
                             'virt_os_variant': 'fedora-unknown',

                             'ssh_pass': 'openEuler12#$',
                             'ssh_user': 'root',

                             'mugen_x': True,
                             'mugen_threads': 1
                             }

        if not set_default:
            with open(yaml_file, 'r') as yfp:
                yld = yaml.YAML(typ='safe')
                yfc = yld.load(yfp)['mugen-libvirt']

                for it in self._config_dict.keys():
                    self._config_dict[it] = yfc[it]

            if self._config_dict['suite_list'] is None or self._config_dict['suite_list'].strip() == "" or \
                    not os.path.isfile(self._config_dict['suite_list']):
                raise CheckError('test_list not exists')
            if self._config_dict['workspace'] is None or self._config_dict['workspace'].strip() == "" or \
                    not os.path.exists(self._config_dict['workspace']):
                raise CheckError('workspace directory not exists')

            self._config_dict['yaml_file'] = yaml_file
            self._config_dict['myon_repo'] = 'https://gitee.com/weilinfox/mugen-libvirt'

        if self._config_dict['ssh_user'] != 'root':
            raise CheckError('ssh_user must be root')

    def yaml_save(self):
        if not self._set_default:
            raise CheckError('yaml_save should only be used to when set_default=True')
        yld = yaml.YAML(typ='rt')
        ylc = 'mugen-libvirt:\n'
        for it in self._config_dict.items():
            ylc += f'  {it[0]}: {it[1]}\n'
        data = yld.load(ylc)
        data['mugen-libvirt'].yaml_add_eol_comment('Number of vCPUs to configure for each guest.', 'virt_vcpus')
        data['mugen-libvirt'].yaml_add_eol_comment('CPU model and features.', 'virt_cpu')
        data['mugen-libvirt'].yaml_add_eol_comment('Configure guest memory allocation in MiB.', 'virt_mem')
        data['mugen-libvirt'].yaml_add_eol_comment('The CPU architecture to simulate.', 'virt_arch')
        data['mugen-libvirt'].yaml_add_eol_comment('See virt-install --boot.', 'virt_boot')
        data['mugen-libvirt'].yaml_add_eol_comment('See virt-install --install.', 'virt_install')
        data['mugen-libvirt'].yaml_add_eol_comment('See virt-install --network.', 'virt_network')
        data['mugen-libvirt'].yaml_add_eol_comment('See virt-install --os-variant.', 'virt_os_variant')
        data['mugen-libvirt'].yaml_add_eol_comment('Must be root.', 'ssh_user')
        data['mugen-libvirt'].yaml_add_eol_comment('Qcow2 image filename, the full path would be workspace/qcow2_image.',
                                    'qcow2_image')

        with open(self._yaml_file, 'w+') as yfp:
            yld.dump(data, yfp)

    def get(self, attr: str):
        return self._config_dict[attr]


def load(yaml_file: str):
    if _have_config():
        return
    if os.path.exists(yaml_file):
        config = _MugenConfig(yaml_file)
        _set_config(config)
    else:
        config = _MugenConfig(yaml_file, set_default=True)
        config.yaml_save()
        log.info("Broken configuration: default configure file is writen to " + yaml_file)


def is_loaded() -> bool:
    return _have_config()


def get(attr: str):
    if not _have_config():
        raise CheckError('Configuration not loaded')

    return _get_config().get(attr)
